import ast
import io
import shutil
import os
import json
import time
import numpy as np
import pandas as pd
import source.record as record
import source.record.signal as mysig
import source.record as record
from platform import system
from PyQt5.QtWidgets import (QMainWindow, QMessageBox, QLineEdit, QMenu, QAction,
                             QTreeWidgetItem, QTableWidgetItem, QHeaderView, QFileDialog, QLabel)
from PyQt5.QtGui import QRegExpValidator, QColor, QBrush, QFont, QPalette, QColor, QBrush
from PyQt5.QtCore import QRegExp, Qt, QPoint
from UI.ui_main_window import Ui_MainWindow
from service.info import Base_Info
from source.runner.run_script import Runner
from source.image_process.case_info import case_info
from source.event import _event
from source.runner.export_script import create_scripts
from service.utils import count_file, create_path, find_file, get_visible_file, open_path, save_json
from service.project_info import PrjInfo, all_prj
from service.import_excel import ImportExcel
from service.image_view import ImageView
from service.aubout import About


record_signals = mysig.RecordSignal()
conf = {
    "is_replay": False
}


class Window(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.init_lance()
        self.recording = False
        self.record = []
        self.running = False
        self.image_list = []
        self.title = ["点击间隔", "按键类别", "事件类型", "输入数据", "比对区域", "相似度", "结果"]
        self.run()
        record.setuphook()
        record.set_callback(self.on_record_event)

    def init_lance(self):
        self.project_name.setValidator(QRegExpValidator(QRegExp(
            "([^\’!\"#$%&\'*+,/:;<=>?@，。?、…【】《》？“”‘’！["u"\\]^`{|}~])*$"), self))
        # "([^\’!\"#$%&\'()*+,-./:;<=>?@，。?、…【】《》？“”‘’！["u"\\]^_`{|}~\s])*$")
        self.case_name.setValidator(QRegExpValidator(QRegExp(
            "([^\’!\"#$%&\'()*+,/:;<=>?@，。?、…【】《》？“”‘’！["u"\\]^`{|}~])*$"), self))
        self.case_num.setValidator(
            QRegExpValidator(QRegExp("^[A-Za-z0-9_.-]+$"), self))
        home_path = os.path.expanduser('~')
        if system() == 'Windows':
            self.data_path = os.path.join(home_path, home_path, "测试数据")
        elif system() == 'Linux':
            self.data_path = os.path.join(home_path, home_path, "测试数据")
        self.record_path = os.path.join(self.data_path, "录制数据")
        self.script_path = os.path.join(self.data_path, "脚本数据")
        self.replay_data = os.path.join(self.data_path, "回放数据")
        self.replay_arch_path = os.path.join(self.data_path, "回放归档")
        create_path(self.record_path)
        create_path(self.script_path)
        create_path(self.replay_data)
        create_path(self.replay_arch_path)
        self.project_box.lineEdit().setPlaceholderText("请输入软件名称查询")
        self.update_prj()
        self.status_bar_lab = self.set_status_bar()
        self.about_window = About()
        conf_file = os.path.join(home_path, '.lance')
        self.wirte_conf(conf_file)

    def wirte_conf(self, conf_file):
        if not os.path.exists(conf_file):
            with open(conf_file, 'w', encoding='utf-8') as file:
                json.dump(conf, file, ensure_ascii=False, indent=4)

    def set_status_bar(self):
        self.status_lab = QLabel()
        self.status_lab.setFont(QFont("Roman times", 10, QFont.Bold))
        return self.status_lab

    def status_bar_show(self, info=None):
        if info == None:
            result = self.check_case_replay()
            is_script = self.check_case_script()
            scripts_path = self.get_scripts_path()
            scripts_cnt = count_file(scripts_path, '.py')
            txt = "当前项目生成脚本共:"+str(scripts_cnt)+"个; " + \
                "当前用例状态:"+result+is_script
        else:
            txt = info
        self.status_bar_lab.clear()
        self.status_bar_lab.setText(txt)
        self.statusBar().addWidget(self.status_bar_lab)

    def set_unedit(self):
        for i in range(self.record_data_table.rowCount()):
            for j in range(1, self.record_data_table.columnCount()):
                item = self.record_data_table.item(i, j)
                if item == None:
                    item = QTableWidgetItem()
                    self.record_data_table.setItem(i, j, item)
                item.setFlags(Qt.ItemFlag(0))
                item.setFlags(Qt.ItemIsEnabled)
        self.record_data_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.record_data_table.horizontalHeader().setSectionResizeMode(0,
                                                                       QHeaderView.Interactive)
        # self.record_data_table.horizontalHeader().setSectionResizeMode(1,
        #                                                                QHeaderView.Interactive)
        # self.record_data_table.horizontalHeader().setSectionResizeMode(2,
        #                                                                QHeaderView.Interactive)
        # self.record_data_table.horizontalHeader().setSectionResizeMode(3,
        #                                                                QHeaderView.Interactive)
        # self.record_data_table.horizontalHeader().setSectionResizeMode(4,
        #                                                                QHeaderView.Interactive)
        # self.record_data_table.horizontalHeader().setSectionResizeMode(5,
        #                                                                QHeaderView.Interactive)
        # self.record_data_table.horizontalHeader().setSectionResizeMode(6,
        #                                                                QHeaderView.Interactive)
        # self.record_data_table.setColumnWidth(0, 85)
        # self.record_data_table.setColumnWidth(1, 100)
        # self.record_data_table.setColumnWidth(2, 200)
        # self.record_data_table.setColumnWidth(3, 180)
        # self.record_data_table.setColumnWidth(4, 280)
        # self.record_data_table.setColumnWidth(5, 100)
        # self.record_data_table.setColumnWidth(6, 50)

    def run(self):
        self.start_record_btn.clicked.connect(self.record_event)
        self.record_screen_btn.clicked.connect(self.record_screenshot)
        self.play_btn.clicked.connect(self.replay)
        self.create_script_btn.clicked.connect(
            lambda: self.create_script(None))
        self.project_box.activated.connect(
            lambda: self.record_check(None))
        self.project_box.activated.connect(self.update_prj)
        self.clear_record_btn.clicked.connect(lambda: self.clear_recod(0))
        self.clear_record_btn.clicked.connect(
            lambda: self.record_data_table.clearContents)
        self.clear_record_btn.clicked.connect(
            lambda: self.record_data_table.setRowCount(0))
        self.clear_record_btn.clicked.connect(lambda: self.record_data_table.setHorizontalHeaderLabels(
            self.title))
        self.project_name.textEdited['QString'].connect(
            lambda: self.record_data_table.setRowCount(0))
        self.project_name.textEdited['QString'].connect(
            lambda: self.record_data_table.setHorizontalHeaderLabels(self.title))
        self.case_name.textEdited['QString'].connect(
            lambda: self.record_data_table.setRowCount(0))
        self.case_name.textEdited['QString'].connect(
            lambda: self.record_data_table.setHorizontalHeaderLabels(self.title))
        self.case_num.textEdited['QString'].connect(
            lambda: self.record_data_table.setRowCount(0))
        self.case_num.textEdited['QString'].connect(
            lambda: self.record_data_table.setHorizontalHeaderLabels(self.title))
        self.case_num.textEdited['QString'].connect(self.update_prj)
        self.record_data_table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.record_data_table.customContextMenuRequested.connect(
            self.record_data_menu)
        self.record_data_table.cellClicked.connect(self.change_cell)
        self.record_data_table.itemDoubleClicked.connect(self.item_image_view)
        self.read_case_file.triggered.connect(self.open_file)
        self.create_script_all.triggered.connect(self.create_all)
        self.about.triggered.connect(self.about_window.open_window)
        self.replay_arch.triggered.connect(self.replay_data_arch)
        self.search_box.textChanged.connect(self.search_case)
        self.preprocess_home.triggered.connect(self.preprocess_home_file)

    def hotkey_event(self, key_name):
        stop_name = 'esc'
        if key_name == stop_name and self.recording:
            self.record_event()
            QMessageBox.information(self, "提示", "录制结束，若显示数据为空请重新录制!")
            self.record_tw.clear()
            self.update_prj()
            self.record_check(self.project_name.text())
        return key_name

    def on_record_event(self, event: _event):
        key_name = event.action[0]
        if event.message == 'key down':
            self.hotkey_event(key_name.lower())
        if key_name == 'esc':
            return
        if self.recording:
            if event.event_type == 'Mouse':
                record = [event.delay, event.event_type, event.message]
                tx, ty = event.action
                record.append(['{0}'.format(tx), '{0}'.format(ty)])
            else:
                record = [event.delay, event.event_type,
                          event.message, event.action]
            self.record.append(record)
            # print('录制事件详细: %s' % event)

    def record_event(self):
        if self.check_project_name() and self.check_case_name() and self.check_case_num() and self.check_case_describ():
            self.case_path = os.path.join(
                self.record_path, self.project_name.text(), self.case_name.text(), self.case_num.text())
            self.case_date = os.path.join(self.case_path, self.case_num.text())
            replay_data = os.path.join(self.replay_data, self.project_name.text(
            ), self.case_name.text(), self.case_num.text())
            scripts_path = os.path.join(self.script_path, self.project_name.text(
            ), self.case_name.text(), self.case_num.text())
            create_path(self.case_path)
            data_csv = self.case_date+'.csv'
            if os.path.exists(data_csv) and os.path.isfile(data_csv):
                self.showNormal()
                ret = self.msg_window(info="已存在录制数据,继续录制请重新点击开始录制按钮！")
                if ret == 1:
                    self.record_data_table.clear()
                    self.record_data_table.setRowCount(0)
                    self.record_data_table.setHorizontalHeaderLabels(
                        self.title)
                    if os.path.exists(self.case_path):
                        shutil.rmtree(self.case_path)
                        if os.path.exists(replay_data):
                            shutil.rmtree(replay_data)
                        if os.path.exists(scripts_path):
                            shutil.rmtree(scripts_path)
                            self.status_bar_show()
            else:
                self.start_record(data_csv)

    def start_record(self, data_csv):
        self.showMinimized()
        if self.recording:
            self.status_bar_show()
            self.recording = False
            data = json.dumps(self.record, indent=1,
                              ensure_ascii=False)
            data = data.replace('\r\n', '\n').replace('\r', '\n')
            data = data.replace('\n   ', '').replace('\n  ', '')
            data = data.replace('\n ]', ']')
            if len(data) > 2:
                data = io.StringIO(json.dumps(self.record, indent=1,
                                              ensure_ascii=False))
                df = pd.read_json(data)
                if not df.empty and df[2][0] == "mouse left up":
                    df = df.drop([0])
                    df.index = np.arange(1, df.shape[0]+1)
                df = pd.DataFrame(df)
                df.columns = ["点击间隔", "按键类别", "事件类型", "输入数据"]
                df.insert(4, column='比对区域', value='')
                df.insert(5, column='相似度', value='')
                df.insert(6, column='结果', value='')
                df.index = np.arange(1, df.shape[0]+1)
                df.index.name = self.case_title.text()
                self.title = df.columns.to_list()
                df.to_csv(data_csv, encoding="utf_8_sig")
                self.show_data(data_csv)
                print("录制数据:", df)
                self.record = []
                print('----------------录制结束----------------')
        else:
            print('----------------开始录制----------------')
            self.record = []
            self.recording = True

    def check_project_name(self):
        if self.project_name.text() != "":
            return True
        else:
            QMessageBox.critical(self, "错误", "项目名不能为空!")
            return False

    def check_case_name(self):
        if self.case_name.text() != "":
            return True
        else:
            QMessageBox.critical(self, "错误", "测试模块名不能为空!")

    def check_case_num(self):
        if self.case_num.text() == "":
            QMessageBox.critical(self, "错误", "用例编号名不能为空!")
        elif len(self.case_num.text()) != 0:
            return True

    def check_case_describ(self):
        if self.case_title.text() == "":
            QMessageBox.critical(self, "错误", "用例描述不能为空!")
        elif len(self.case_title.text()) != 0:
            return True

    def check_case_script(self):
        scripts_path = os.path.join(self.script_path, self.project_name.text(
        ), self.case_name.text(), self.case_num.text(), self.case_num.text()+'.csv')
        if os.path.exists(scripts_path) and os.path.isfile(scripts_path):
            return '脚本已生成。'
        else:
            return '未生成脚本。'

    def check_case_replay(self):
        replay_path = os.path.join(self.replay_data, self.project_name.text(
        ), self.case_name.text(), self.case_num.text())
        replay_data = os.path.join(replay_path, self.case_num.text()+".csv")
        if os.path.exists(replay_data) and os.path.isfile(replay_data):
            df = pd.read_csv(replay_data, index_col=0)
            if '比对区域' not in df.columns.to_list():
                df.columns.to_list().insert(4, '比对区域')
                df.reindex(columns=df.columns.to_list())
                df.insert(loc=4, column='比对区域', value='nan')
            if '相似度' not in df.columns.to_list():
                df.columns.to_list().insert(5, '相似度')
                df.reindex(columns=df.columns.to_list())
                df.insert(loc=5, column='相似度', value='nan')
            if '结果' not in df.columns.to_list():
                df.columns.to_list().insert(6, '结果')
                df.reindex(columns=df.columns.to_list())
                df.insert(loc=6, column='结果', value='nan')
            df.to_csv(replay_data, columns=df.columns.to_list(),
                      encoding='utf_8_sig')
            result = list(set(df.loc[:]["结果"].tolist()))
            result = np.array(result).tolist()
            for i in result:
                if i == 'nan':
                    result.remove(i)
            if ['通过'] == result:
                print("回放结果", result)
                return "回放通过，"
            else:
                return "回放失败，"
        else:
            return "未回放，"

    def record_screenshot(self):
        print('----------------开始录制截图------------')
        if self.check_project_name() and self.check_case_name() and self.check_case_num() and self.check_case_describ():
            self.case_path = os.path.join(self.record_path, self.project_name.text(),
                                          self.case_name.text(), self.case_num.text())
            self.expect_image_path = os.path.join(
                self.case_path, 'expect_image')
            self.case_date = os.path.join(
                self.case_path, self.case_num.text()+".csv")
            create_path(self.expect_image_path)
            if not os.path.exists(self.case_date):
                ret = self.msg_window(
                    title="错误", info="项目录制数据不存在!", flag=False)
                if ret == 1:
                    self.showMinimized()
            else:
                ret = self.check_double_click()
                if ret == []:
                    self.showMinimized()
                    run = Runner(self.case_date, self.expect_image_path)
                    ret = run.screenshot(1, self.expect_image_path)
                    if ret == True:
                        QMessageBox.information(self, "提示", "录制截图正常.")
                        self.status_bar_show()
                    elif len(os.listdir(self.expect_image_path)) == 0:
                        QMessageBox.critical(self, "错误", "无效录制,录制操作无鼠标和键盘输入.")
                    else:
                        QMessageBox.critical(self, "错误", "截图与实际操作统计截图不一致.")
                else:
                    msg = [str(number) for number in ret]
                    msg = ' '.join(msg)
                    QMessageBox.critical(self, "错误", "请检查如下步骤双击坐标点是否一致,并确认预期结果图片是否一致:\n"+msg)
        print('----------------录制截图结束------------')

    def check_double_click(self):
        df = pd.read_csv(self.case_date, index_col=0)
        double_steps = []
        for run_step in range(0, df.shape[0]):
            all_step = df.shape[0]
            click_delay = df.iloc[run_step, 0]
            press_type = df.iloc[run_step, 1]
            event_type = df.iloc[run_step, 2]
            input_data = eval(
                df.iloc[run_step, 3].replace("", ""))
            if event_type == 'mouse left up':
                next_up = run_step+2
                if next_up < all_step:
                    next_press_type = df.iloc[next_up, 1]
                    next_event_type = df.iloc[next_up, 2]
                    next_input_data = eval(
                        df.iloc[next_up, 3].replace("", ""))
                    if event_type == next_event_type:
                        run_step = next_up
                        double_click = (df.iloc[run_step-3:run_step +
                                                1, df.columns.get_loc('输入数据')].tolist())
                        converted_data = [ast.literal_eval(
                            point) for point in double_click]
                        all_elements_equal = all(
                            element == converted_data[0] for element in converted_data)
                        if all_elements_equal == False:
                            double_steps.append(run_step+1)
        print("错误双击步骤：", double_steps)
        return double_steps

    def get_case_path(self):
        case_path = os.path.join(self.record_path, self.project_name.text(
        ), self.case_name.text(), self.case_num.text())
        return case_path

    def get_record_data(self):
        case_path = self.get_case_path()
        case_date = os.path.join(case_path, self.case_num.text()+'.csv')
        return case_date

    def get_replay_path(self):
        replay_path = os.path.join(self.replay_data,  self.project_name.text(
        ), self.case_name.text(), self.case_num.text())
        return replay_path

    def get_replay_data(self):
        replay_path = self.get_replay_path()
        replay_data = os.path.join(replay_path, self.case_num.text()+".csv")
        return replay_data

    def get_scripts_path(self):
        scripts_path = os.path.join(self.script_path, self.project_name.text())
        return scripts_path

    def replay(self):
        replay_path = self.get_replay_path()
        print("回放用例:", replay_path)
        if os.path.exists(replay_path):
            shutil.rmtree(replay_path)
            create_path(replay_path)
        self.create_script(self.replay_data)
        case_script = os.path.join(self.replay_data, self.project_name.text(
        ), self.case_name.text(), self.case_num.text(), self.case_num.text()+'.py')
        case_data = os.path.join(self.replay_data, self.project_name.text(
        ), self.case_name.text(), self.case_num.text(), self.case_num.text()+'.csv')
        cmd = '/usr/bin/python3 ' + '"'+case_script+'"'
        # cmd = 'python3 ' + '"'+case_script+'"'
        self.showMinimized()
        res = os.popen(cmd).read()
        self.show_data(case_data)
        QMessageBox.information(self, "提示", "回放结束！")
        self.status_bar_show()

    def get_cell_value(self, row_index, column_index):
        if 0 <= row_index < self.record_data_table.rowCount() and 0 <= column_index < self.record_data_table.columnCount():
            item = self.record_data_table.item(row_index, column_index)
            if item is not None:
                return item.text()
            else:
                return ""
        else:
            # print("无效的行/列索引")
            return ""

    def record_data_menu(self, pos):
        clicked_row = self.record_data_table.rowAt(pos.y())
        clicked_col = self.record_data_table.columnAt(pos.x())
        is_mouse_left_up = self.get_cell_value(clicked_row, 2)
        if is_mouse_left_up == 'mouse left up' and clicked_col == 4:
            menu = QMenu(self)
            x = pos.x()+38
            y = pos.y()+30
            pos = QPoint(x, y)
            font = QFont("Arial", 13)
            menu.setFont(font)

            sub_clear = QMenu("清除区域", self)
            font = QFont("Arial", 12)
            sub_clear.setFont(font)
            clear_current_area = QAction("清除当前步骤区域", sub_clear)
            clear_all_area = QAction("清除当前用例所有区域", sub_clear)
            sub_clear.addAction(clear_current_area)
            sub_clear.addAction(clear_all_area)
            clear_current_area.triggered.connect(self.clear_current_area)
            clear_all_area.triggered.connect(self.clear_all_area)

            sub_set_menu = QMenu("设置区域", self)
            font = QFont("Arial", 12)
            sub_set_menu.setFont(font)
            set_current_case_area = QAction("设置当前用例比对区域相同", sub_set_menu)
            set_all_case_area = QAction("设置所有用例比对区域相同", sub_set_menu)
            sub_set_menu.addAction(set_current_case_area)
            sub_set_menu.addAction(set_all_case_area)
            set_current_case_area.triggered.connect(self.replace_all_area)
            set_all_case_area.triggered.connect(self.replace_all_case_area)

            sub_check_menu = QMenu("查看数据", self)
            font = QFont("Arial", 12)
            sub_check_menu.setFont(font)
            check_record = QAction("查看录制数据", sub_check_menu)
            check_replay = QAction("查看回放数据", sub_check_menu)
            check_scrip = QAction("查看用例脚本", sub_check_menu)
            sub_check_menu.addAction(check_record)
            sub_check_menu.addAction(check_replay)
            sub_check_menu.addAction(check_scrip)
            check_record.triggered.connect(self.open_record)
            check_replay.triggered.connect(self.open_replay)
            check_scrip.triggered.connect(self.open_scrip)

            menu.addMenu(sub_clear)
            menu.addMenu(sub_set_menu)
            menu.addMenu(sub_check_menu)
            menu.exec_(self.record_data_table.mapToGlobal(pos))

    def open_record(self):
        record_path = self.get_case_path()
        if os.path.exists(record_path):
            open_path(record_path)
        else:
            QMessageBox.critical(self, "错误", "不存在录制数据！")

    def open_replay(self):
        replay_path = self.get_replay_path()
        if os.path.exists(replay_path):
            open_path(replay_path)
        else:
            QMessageBox.critical(self, "错误", "不存在回放数据！")

    def open_scrip(self):
        script_path = self.get_scripts_path()
        script_path = os.path.join(
            script_path, self.case_name.text(), self.case_num.text())
        if os.path.exists(script_path):
            open_path(script_path)
        else:
            QMessageBox.critical(self, "错误", "不存在脚本数据！")

    def clear_current_area(self):
        current_row = self.record_data_table.currentRow()
        self.record_data_table.setItem(
            current_row, 4, QTableWidgetItem("nan"))
        self.update_record_tw()

    def clear_all_area(self):
        for i in range(self.record_data_table.rowCount()):
            self.record_data_table.setItem(i, 4, QTableWidgetItem("nan"))
        self.update_record_tw()

    def replace_all_area(self):
        current_row = self.record_data_table.currentRow()
        current_area = self.record_data_table.item(current_row, 4).text()
        for i in range(self.record_data_table.rowCount()):
            self.record_data_table.setItem(
                i, 4, QTableWidgetItem(current_area))
        self.update_record_tw()

    def replace_all_case_area(self):
        current_path = os.path.join(self.record_path, self.project_name.text())
        csv_path = find_file(current_path, '.csv')
        replay_path = os.path.join(self.replay_data, self.project_name.text())
        replay_csv = find_file(replay_path, '.csv')
        all_data = csv_path + replay_csv
        current_row = self.record_data_table.currentRow()
        current_area = self.record_data_table.item(current_row, 4).text()
        for csv in all_data:
            df = pd.read_csv(csv, encoding='utf_8_sig', index_col=0)
            # if '相似度' not in df.columns.to_list():
            #     df.columns.to_list().insert(5, '相似度')
            #     df.reindex(columns=df.columns.to_list())
            #     df.insert(loc=5, column='相似度', value='nan')
            # if '结果' not in df.columns.to_list():
            #     df.columns.to_list().insert(6, '结果')
            #     df.reindex(columns=df.columns.to_list())
            #     df.insert(loc=6, column='结果', value='nan')
            if '比对区域' not in df.columns.to_list():
                df.columns.to_list().insert(4, '比对区域')
                df.reindex(columns=df.columns.to_list())
                df.insert(loc=4, column='比对区域', value='nan')
                df['比对区域'] = current_area
                df.to_csv(csv, columns=df.columns.to_list(),
                          encoding='utf_8_sig')
            else:
                df['比对区域'] = current_area
                df.to_csv(csv, columns=df.columns.to_list(),
                          encoding='utf_8_sig')
        self.replace_all_area()
        self.update_record_tw()

    def update_record_tw(self):
        data = []
        headerLabels = []
        for col in range(self.record_data_table.columnCount()):
            header = self.record_data_table.horizontalHeaderItem(col)
            if header is not None:
                headerLabels.append(header.text())
        for row in range(self.record_data_table.rowCount()):
            rowData = []
            for column in range(self.record_data_table.columnCount()):
                item = self.record_data_table.item(row, column)
                if item is not None:
                    rowData.append(item.text())
            data.append(rowData)

        df = pd.DataFrame(data, columns=headerLabels)
        df.index = np.arange(1, df.shape[0]+1)
        df.index.name = self.case_title.text()
        current_data = self.get_record_data()
        replay_data = self.get_replay_data()
        if os.path.exists(current_data):
            tmp = df.copy()
            tmp['相似度'] = np.nan
            tmp['结果'] = np.nan
            tmp.to_csv(current_data, encoding="utf_8_sig")
            if os.path.exists(replay_data):
                df.to_csv(replay_data, encoding="utf_8_sig")
                self.show_data(replay_data)
            else:
                self.show_data(current_data)
                pass
        data.clear()

    def get_data(self, flag=1):
        product_name = self.project_name.text()
        model_name = self.case_name .text()
        case_name = self.case_num.text()
        path = self.record_path
        if flag == 2:
            path = self.replay_data
        case_path = os.path.join(path, product_name, model_name, case_name)
        data = os.path.join(case_path, case_name+'.csv')
        return data

    def change_cell(self, row, column):
        self.set_unedit()
        case_title = self.case_title.text()
        item = self.record_data_table.item(row, column)
        if item is not None and column == 0:
            text = item.text()
            line_edit = QLineEdit(text)
            self.record_data_table.setCellWidget(row, column, line_edit)
            line_edit.editingFinished.connect(
                lambda: self.update_cell(row, column, line_edit, case_title))

    def update_cell(self, row, column, line_edit, case_title):
        palette = line_edit.palette()
        palette.setColor(QPalette.Base, QColor(0, 255, 0))
        palette.setColor(QPalette.Base, QColor(0, 255, 0, 255))
        line_edit.setAutoFillBackground(True)
        line_edit.setPalette(palette)
        text = line_edit.text()
        item = QTableWidgetItem(text)
        self.record_data_table.setItem(row, column, item)
        df = pd.DataFrame(columns=self.title)
        current_data = self.get_data()
        replay_data = self.get_data(flag=2)
        data = []
        for row in range(self.record_data_table.rowCount()):
            rowData = []
            for column in range(self.record_data_table.columnCount()):
                item = self.record_data_table.item(row, column)
                if item is not None:
                    rowData.append(item.text())
            data.append(rowData)
        df = pd.DataFrame(data)
        # df = df.drop([0])
        df.index = np.arange(1, df.shape[0]+1)
        df.columns = self.title
        df.index.name = case_title
        delay_list = df['点击间隔'].to_list()
        if self.check_delay(delay_list, line_edit) != False:
            if os.path.exists(current_data):
                tmp = df.copy()
                tmp['相似度'] = np.nan
                tmp['结果'] = np.nan
                tmp.to_csv(current_data, encoding="utf_8_sig")
            if os.path.exists(replay_data):
                df.to_csv(replay_data, encoding="utf_8_sig")
        else:
            QMessageBox.critical(self, "错误", "亲~ 点击间隔是个整数,单位是毫秒!")

    def check_delay(self, delay_list, line_edit):
        flag = True
        for i in delay_list:
            if not i.isdigit():
                palette = line_edit.palette()
                palette.setColor(QPalette.Base, QColor(255, 0, 0))
                palette.setColor(QPalette.Base, QColor(255, 0, 0, 255))
                line_edit.setAutoFillBackground(True)
                line_edit.setPalette(palette)
                flag = False
        return flag

    def create_all(self):
        prj_info = all_prj(self.record_path)
        for k, v in prj_info.items():
            for case_name in v:
                case_path = os.path.join(k, case_name)
                case_file = os.path.join(case_path, case_name+'.csv')
                export_path = self.script_path + case_path.split("录制数据")[1]
                run_image_path = os.path.join(
                    export_path, "runtime_image")
                image_path = os.path.join(case_path, 'expect_image')
                if os.path.exists(case_file) and os.path.exists(image_path):
                    ret = case_info(case_file, image_path)
                    if isinstance(ret, list):
                        create_path(run_image_path)
                        create_scripts(case_file, 1)
                        shutil.copytree(case_path, export_path,
                                        dirs_exist_ok=True)
        QMessageBox.information(self, "提示", "所有项目脚本生成结束！")

    def create_script(self, path=None):
        if self.check_project_name() and self.check_case_name() and self.check_case_num() and self.check_case_describ():
            case_path = os.path.join(self.record_path, self.project_name.text(),
                                     self.case_name.text(), self.case_num.text())
            record_data = os.path.join(
                case_path, self.case_num.text()+'.csv')
            image_path = os.path.join(case_path, 'expect_image')
            if os.path.exists(image_path):
                ret = case_info(record_data, image_path)
                if isinstance(ret, list):
                    case_path = os.path.join(
                        self.record_path, self.project_name.text(), self.case_name.text(), self.case_num.text())
                    if path == None:
                        export_path = os.path.join(
                            self.script_path, self.project_name.text(), self.case_name.text(), self.case_num.text())
                    else:
                        export_path = os.path.join(
                            path, self.project_name.text(), self.case_name.text(), self.case_num.text())
                    if os.path.exists(case_path):
                        shutil.copytree(case_path, export_path,
                                        dirs_exist_ok=True)
                        record_data = os.path.join(
                            export_path, self.case_num.text()+".csv")
                        run_image_path = os.path.join(
                            export_path, "runtime_image")
                        create_path(run_image_path)
                        create_scripts(record_data, 1)
                        if path == None:
                            QMessageBox.information(
                                self, "提示", "用例"+self.case_num.text()+"脚本已生成!")
                        self.status_bar_show()
                    else:
                        QMessageBox.critical(self, "错误", "请检查是否存在此项目录制.")
                elif ret == 0:
                    QMessageBox.critical(self, "错误", "录制截图数量大于录制数据应该截图的数量.")
                elif ret == 1:
                    QMessageBox.critical(self, "错误", "录制截图数量小于录制数据应该截图的数量.")
            else:
                QMessageBox.critical(self, "错误", "生成脚本前需要执行当前用例录制截图操作.")

    def record_check(self, prj_name=None):
        record_path = self.record_path
        prj_info = PrjInfo(record_path)
        all_prj_name = prj_info.get_prj_name()
        test_items = prj_info.get_test_items()
        if prj_name == None:
            current_prj = self.project_box.currentText()
        else:
            current_prj = self.project_name.text()
        self.record_tw.clear()
        if current_prj in all_prj_name:
            find_case = test_items.get(current_prj)
            self.tree = self.record_tw
            self.tree.setColumnCount(1)
            self.root = QTreeWidgetItem(self.tree)
            self.root.setText(0, current_prj)
            for i in find_case:
                case_name = QTreeWidgetItem(self.root)
                case_name.setText(0, i)
                all_case_path = os.path.join(record_path, current_prj, i)
                all_case_name = os.listdir(all_case_path)
                if len(all_case_name) != 0:
                    for j in all_case_name:
                        case_num = QTreeWidgetItem(case_name)
                        case_num.setText(0, j)
                        self.root.addChild(case_num)
                        case_file = os.path.join(
                            record_path, current_prj, i, j, j+'.csv')
                        if not os.path.exists(case_file):
                            case_num.setForeground(0, QColor(255, 0, 0))

            self.tree.clicked.connect(
                lambda: self.tree_clicked(record_path, self.root, self.record_tw))
            self.tree.addTopLevelItem(self.root)
            self.tree.expandAll()
        else:
            self.clear_ui()
            self.record_data_table.setRowCount(0)
            self.record_data_table.setHorizontalHeaderLabels(
                self.title)
        self.project_box.lineEdit().clear()

    def clear_ui(self):
        self.case_title.clear()
        self.project_name.clear()
        self.case_num.clear()
        self.case_name.clear()

    def tree_clicked(self, record_path, root, tree):
        prj_name = ''
        case_name = ''
        case_num = ''
        try:
            prj_name = root.text(0)
            case_name = tree.currentItem().parent().text(0)
            case_num = tree.currentItem().text(0)
        except:
            pass
        csv_file = os.path.join(record_path, prj_name,
                                case_name, case_num, case_num+'.csv')
        replay_csv_file = os.path.join(
            self.replay_data, prj_name, case_name, case_num, case_num+'.csv')
        if os.path.exists(csv_file) and os.path.isfile(csv_file):
            if os.path.exists(replay_csv_file) and os.path.isfile(replay_csv_file):
                data = replay_csv_file
                flag = 1
            else:
                data = csv_file
                flag = 0
            df = pd.read_csv(data, index_col=0)
            if '比对区域' not in df.columns.to_list():
                df.columns.to_list().insert(4, '比对区域')
                df.reindex(columns=df.columns.to_list())
                df.insert(loc=4, column='比对区域', value='nan')
            if '相似度' not in df.columns.to_list():
                df.columns.to_list().insert(5, '相似度')
                df.reindex(columns=df.columns.to_list())
                df.insert(loc=5, column='相似度', value='nan')
            if '结果' not in df.columns.to_list():
                df.columns.to_list().insert(6, '结果')
                df.reindex(columns=df.columns.to_list())
                df.insert(loc=6, column='结果', value='nan')
            df_rows = df.shape[0]
            df_colunms = df.shape[1]
            self.record_data_table.setColumnCount(df_colunms)
            self.record_data_table.clear()
            self.record_data_table.setRowCount(df_rows)
            self.record_data_table.setHorizontalHeaderLabels(
                self.title)
            for i in range(df_rows):
                df_rows_values = df.iloc[[i]]
                df_rows_values_array = np.array(
                    df_rows_values)
                df_rows_values_list = df_rows_values_array.tolist()[
                    0]
                for j in range(df_colunms):
                    df_items_list = df_rows_values_list[j]
                    df_items = str(df_items_list)
                    new_item = QTableWidgetItem(df_items)
                    self.record_data_table.setItem(i, j, new_item)
                    self.record_data_table.horizontalHeader().setSectionResizeMode(
                        QHeaderView.Stretch)
            self.clear_ui()
            self.project_name.setText(prj_name)
            self.case_name.setText(case_name)
            self.case_num.setText(case_num)
            self.case_title.setText(df.index.name)
            self.mark_steps(data, flag)
        else:
            self.record_data_table.clear()
            self.record_data_table.setRowCount(0)
            self.record_data_table.setHorizontalHeaderLabels(self.title)
            self.project_name.setText(prj_name)
            self.case_name.setText(case_name)
            self.case_num.setText(case_num)
        self.status_bar_show()

    def show_data(self, csv_file):
        if os.path.exists(csv_file) and os.path.isfile(csv_file):
            df = pd.read_csv(csv_file, index_col=0)
            # if '比对区域' not in df.columns.to_list():
            #     df.columns.to_list().insert(4, '比对区域')
            #     df.reindex(columns=df.columns.to_list())
            #     df.insert(loc=4, column='比对区域', value='')
            df_rows = df.shape[0]
            df_colunms = df.shape[1]
            df_header = df.columns.values.tolist()
            self.record_data_table.setColumnCount(df_colunms)
            self.record_data_table.clear()
            self.record_data_table.setRowCount(df_rows)
            self.record_data_table.setHorizontalHeaderLabels(df_header)
            for i in range(df_rows):
                df_rows_values = df.iloc[[i]]
                df_rows_values_array = np.array(df_rows_values)
                df_rows_values_list = df_rows_values_array.tolist()[0]
                for j in range(df_colunms):
                    df_items_list = df_rows_values_list[j]
                    df_items = str(df_items_list)
                    new_item = QTableWidgetItem(df_items)
                    self.record_data_table.setItem(i, j, new_item)
                    self.record_data_table.horizontalHeader().setSectionResizeMode(
                        QHeaderView.Stretch)
        current_data = self.get_record_data()
        replay_data = self.get_replay_data()
        if os.path.exists(csv_file):
            if current_data == csv_file:
                self.mark_steps(current_data, 0)
            else:
                pass
            if replay_data == csv_file:
                self.mark_steps(replay_data, 1)
            else:
                pass

    def mark_steps(self, csv_file, flag):
        ret = case_info(csv_file)
        df = pd.read_csv(csv_file)
        if isinstance(ret, list):
            if flag == 0:
                colum_cnt = self.record_data_table.columnCount()
                for i in ret:
                    row = int(i.split('.')[0])-1
                    for j in range(1, colum_cnt):
                        self.record_data_table.item(row, j).setBackground(
                            QBrush(QColor(0, 190, 255)))
            if flag == 1:
                colum_cnt = self.record_data_table.columnCount()
                for i in ret:
                    row = int(i.split('.')[0])-1
                    for j in range(1, colum_cnt):
                        if '结果' in df.columns.to_list():
                            if df.loc[row, '结果'] == '通过':
                                self.record_data_table.item(row, j).setBackground(
                                    QBrush(QColor(0, 250, 26)))
                            else:
                                self.record_data_table.item(row, j).setBackground(
                                    QBrush(QColor(255, 39, 0)))
        self.set_unedit()

    def msg_window(self, title="警告", info="", btny_txt="Yes", btnx_txt="No", flag=True):
        self.showMinimized()
        msg_box = QMessageBox()
        msg_box.setWindowTitle(title)
        msg_box.setText(info)
        if flag:
            msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            btn_y = msg_box.button(QMessageBox.Yes)
            btn_n = msg_box.button(QMessageBox.No)
            btn_y.setText(btny_txt)
            btn_n.setText(btnx_txt)
            msg_box.exec_()
            if msg_box.clickedButton() == btn_y:
                msg_box.deleteLater()
                return 1
            elif msg_box.clickedButton() == btn_n:
                msg_box.deleteLater()
                return 2
        else:
            msg_box.setStandardButtons(QMessageBox.Yes)
            btn_y = msg_box.button(QMessageBox.Yes)
            btn_y.setText(btny_txt)
            msg_box.exec_()
            if msg_box.clickedButton() == btn_y:
                msg_box.deleteLater()
                return 1

    def clear_recod(self, flag):
        current_prj = self.project_name.text()
        current_case = self.case_name.text()
        current_num = self.case_num.text()
        case_path = os.path.join(
            self.record_path, current_prj, current_case, current_num)
        replay_data = os.path.join(self.replay_data, self.project_name.text(
        ), self.case_name.text(), self.case_num.text())
        scripts_path = os.path.join(self.script_path, self.project_name.text(
        ), self.case_name.text(), self.case_num.text())
        if flag == 0:
            if self.check_project_name() and self.check_case_name() and self.check_case_num():
                info = "是否删除当前用例!"
                ret = self.msg_window(info=info)
                if ret == 1:
                    if os.path.exists(case_path):
                        shutil.rmtree(case_path)
                    if os.path.exists(replay_data):
                        shutil.rmtree(replay_data)
                    if os.path.exists(scripts_path):
                        shutil.rmtree(scripts_path)
                    QMessageBox.information(self, "提示", "测试用例已删除！")
                    self.record_check(self.project_name.text())
                else:
                    pass
            else:
                QMessageBox.critical(self, "错误", "请检查输入项！")
        elif flag == 1:
            info = "是否删除所有项目！"
            ret = self.msg_window(info=info)
            if ret == 1:
                shutil.rmtree(self.record_path)

    def update_prj(self):
        prj = PrjInfo(self.record_path)
        items = []
        items.clear()
        self.project_box.addItems(items)
        self.project_box.clear()
        items = sorted(prj.get_prj_name())
        self.project_box.addItems(items)
        self.project_box.lineEdit().clear()

    def update_case_file(self, data):
        self.record_tw.clear()
        self.record_data_table.setRowCount(0)
        self.record_data_table.setHorizontalHeaderLabels(self.title)
        case = ImportExcel(data)
        case.full_case_dict
        case_list = case.get_invalid_model_row()
        if case_list != []:
            QMessageBox.critical(
                self, "错误", data+"文件不规范用例行:\n"+",".join('%s' % id for id in case_list))
        else:
            prj_name = ''.join(list(set(case.df['产品名称'])))
            tree = self.record_tw
            root = QTreeWidgetItem(tree)
            root.setText(0, prj_name)
            all_case = case.all_qversion
            print(all_case)
            for item in all_case:
                for k, v in item.items():
                    case_name = QTreeWidgetItem(root)
                    case_name.setText(0, k)
                    case_list = []
                    if v != []:
                        for i in v:
                            num = case.df.loc[i]['自动化用例编号']
                            case_list.append(num)
                            case_path = os.path.join(
                                self.data_path, self.record_path, prj_name, k, num)
                            create_path(case_path)
                        for j in range(len(case_list)):
                            case_num = QTreeWidgetItem(case_name)
                            case_num.setText(0, str(case_list[j]))
                            case_file = os.path.join(
                                self.record_path, prj_name, k, str(case_list[j]), str(case_list[j])+'.csv')
                            if not os.path.exists(case_file) and not os.path.isfile(case_file):
                                case_num.setForeground(0, QColor(255, 0, 0))
                        case_list.clear()

            tree.addTopLevelItem(root)
            # tree.expandAll()
            tree.itemDoubleClicked.connect(
                lambda: self.fill_input(root, tree, data))
            QMessageBox.information(
                self, "导入用例统计", "导入Q版本用例总数:"+str(len(case.q_version_case)))

    def fill_input(self, root, tree, data):
        try:
            df = pd.read_excel(data, dtype={'自动化用例编号': str})
            prj_name = root.text(0)
            case_name = tree.currentItem().parent().text(0)
            case_num = tree.currentItem().text(0)
            idx = case_num
            num = df.loc[df['自动化用例编号'] == idx].index.values[0]
            case_tilte = df.loc[num]['用例标题']
            if pd.isnull(case_tilte):
                case_tilte = ''
            self.project_name.setText(prj_name)
            self.case_name.setText(case_name)
            self.case_num.setText(case_num)
            self.case_title.setText(str(case_tilte))
        except:
            pass

    def open_file(self):
        case_path, _ = QFileDialog.getOpenFileName(
            self, "选择测试用例文件", os.path.expanduser('~'), "excel(*.xls * xlsx)")
        if case_path == '':
            return
        case_name = ''
        for i in case_path:
            case_name += i
        case_name = case_name.split('/')[-1]
        if case_name.split('.')[-1] == 'xls' or case_name.split('.')[-1] == 'xlsx':
            self.clear_ui()
            self.record_data_table.clear()
            self.record_tw.clear()
            self.update_case_file(case_path)

    def closeEvent(self, event):
        result = QMessageBox.question(
            self, "提示", "确定退出?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if result == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

    def item_image_view(self, row):
        case_path = os.path.join(self.record_path, self.project_name.text(
        ), self.case_name.text(), self.case_num.text())
        expect_img_path = os.path.join(case_path, 'expect_image')
        case_data = os.path.join(case_path, self.case_num.text()+'.csv')
        if os.path.exists(expect_img_path) and os.path.exists(case_data):
            self.image_window = ImageView()
            self.image_window.pre_btn.setEnabled(True)
            self.image_window.next_btn.setEnabled(True)
            self.image_window.pre_btn.clicked.connect(
                lambda: self.image_view(1))
            self.image_window.next_btn.clicked.connect(
                lambda: self.image_view(2))
            self.image_view_status_lab = self.image_window.set_status_bar()
            case_replay_path = os.path.join(self.replay_data, self.project_name.text(
            ), self.case_name.text(), self.case_num.text())

            run_img_path = os.path.join(case_replay_path, 'runtime_image')
            case_data = os.path.join(case_path, self.case_num.text()+'.csv')
            case_replay_data = os.path.join(
                case_replay_path, self.case_num.text()+'.csv')
            image_list = case_info(case_data)
            if os.path.exists(case_data) and os.path.exists(case_replay_data):
                df = pd.read_csv(case_replay_data, index_col=0)
            elif os.path.exists(case_data):
                df = pd.read_csv(case_data, index_col=0)
                case_replay_data = case_data
            # else:
            #     ret = self.msg_window(info="非法删除当前用例数据!是否重启lance?")
            #     if ret == 1:
            #         QCoreApplication.quit()
            #         QProcess.startDetached(sys.executable, sys.argv)
            #     else:
            #         sys.exit(0)
            row = str(row.row()+1)
            row_img = row+'.png'
            result = 'nan'
            if image_list != -1 and row_img in image_list:
                self.image_window.open_window()
                current_title_name = self.image_window.windowTitle()
                current_step = current_title_name[3:len(
                    current_title_name)].split("步")[0]
                expect_image = os.path.join(expect_img_path, row_img)
                run_image = os.path.join(run_img_path, row_img)
                if os.path.exists(expect_image):
                    self.image_window.show_image(
                        expect_image, self.image_window.expect_gv, 1, case_data, case_replay_data)
                    if not os.path.exists(run_image):
                        self.image_view_status_lab.setText("不存在运行结果图片")
                    else:
                        self.image_window.show_image(
                            run_image, self.image_window.run_gv, 2, case_data, case_replay_data)
                        if os.path.exists(case_replay_data):
                            result = df.loc[int(row_img.split(".")[0])]['结果']
                else:
                    self.image_view_status_lab.setText("预期结果图片和运行结果图片均不存在")
                self.image_window.setWindowTitle(
                    "查看第%s步图片,结果:%s" % (row_img.split(".")[0], result))
                self.image_window.statusBar().addWidget(self.image_view_status_lab)
            try:
                self.image_window._signal.connect(self.update_area)
            except:
                pass

    def update_area(self, data):
        self.show_data(data)
        self.set_unedit()

    def image_view(self, flag):
        case_path = os.path.join(
            self.record_path, self.project_name.text(), self.case_name.text(), self.case_num.text())
        case_replay_path = os.path.join(self.replay_data, self.project_name.text(
        ), self.case_name.text(), self.case_num.text())
        expect_img_path = os.path.join(case_path, 'expect_image')
        run_img_path = os.path.join(case_replay_path, 'runtime_image')
        case_data = os.path.join(case_path, self.case_num.text()+'.csv')
        case_replay_data = os.path.join(
            case_replay_path, self.case_num.text()+'.csv')
        image_list = case_info(case_data)
        if os.path.exists(case_data) and os.path.exists(case_replay_data):
            df = pd.read_csv(case_replay_data, index_col=0)
        else:
            df = pd.read_csv(case_data, index_col=0)
            case_replay_data = case_data
        current_title_name = self.image_window.windowTitle()
        current_step = current_title_name[3:len(
            current_title_name)].split("步")[0]
        current_image_name = current_step+'.png'
        if flag == 1:
            self.image_view_status_lab.clear()
            self.image_window.next_btn.setEnabled(True)

            if current_image_name in image_list:
                idx = image_list.index(current_image_name)
                pre = idx - 1
                if pre < 0:
                    pre = 0
                if pre > 0:
                    expect_image = os.path.join(
                        expect_img_path, image_list[pre])
                    run_image = os.path.join(run_img_path, image_list[pre])
                else:
                    self.image_window.pre_btn.setEnabled(False)
                    expect_image = os.path.join(
                        expect_img_path, image_list[0])
                    run_image = os.path.join(run_img_path, image_list[0])
                result = 'nan'
                if os.path.exists(expect_image):
                    self.image_window.show_image(
                        expect_image, self.image_window.expect_gv, 1, case_data, case_replay_data)
                    if not os.path.exists(run_image):
                        self.image_view_status_lab.setText("不存在运行结果图片")
                    else:
                        self.image_window.show_image(
                            run_image, self.image_window.run_gv, 2, case_data, case_replay_data)
                        if os.path.exists(case_replay_data):
                            result = df.loc[int(
                                image_list[pre].split(".")[0])]["结果"]
                else:
                    self.image_view_status_lab.setText("预期结果图片和运行结果图片均不存在")
                self.image_window.setWindowTitle(
                    "查看第%s步图片,结果:%s" % (image_list[pre].split(".")[0], result))
                self.image_window.statusBar().addWidget(self.image_view_status_lab)
        if flag == 2:
            self.image_view_status_lab.clear()
            self.image_window.pre_btn.setEnabled(True)
            current_title_name = self.image_window.windowTitle()
            if current_image_name in image_list:
                idx = image_list.index(current_image_name)
                next = idx + 1
                if next > len(image_list) - 1:
                    next = len(image_list) - 1
                if next < len(image_list)-1:
                    expect_image = os.path.join(
                        expect_img_path, image_list[next])
                    run_image = os.path.join(
                        run_img_path, image_list[next])
                else:
                    self.image_window.next_btn.setEnabled(False)
                    expect_image = os.path.join(
                        expect_img_path, image_list[len(image_list)-1])
                    run_image = os.path.join(
                        run_img_path, image_list[len(image_list)-1])
                result = 'nan'
                if os.path.exists(expect_image):
                    self.image_window.show_image(
                        expect_image, self.image_window.expect_gv, 1, case_data, case_replay_data)
                    if not os.path.exists(run_image):
                        self.image_view_status_lab.setText("不存在运行结果图片")
                    else:
                        self.image_window.show_image(
                            run_image, self.image_window.run_gv, 2, case_data, case_replay_data)
                        if os.path.exists(case_replay_data):
                            result = df.loc[int(
                                image_list[next].split(".")[0])]["结果"]
                else:
                    self.image_view_status_lab.setText("预期结果图片和运行结果图片均不存在")
                self.image_window.setWindowTitle("查看第%s步图片,结果:%s" % (
                    image_list[next].split(".")[0], result))
                self.image_window.statusBar().addWidget(self.image_view_status_lab)
        self.image_window._signal.connect(self.update_area)

    def replay_data_arch(self):
        save_time = round(time.time()*1000)
        info = Base_Info()
        if self.check_case_replay() != "未回放，":
            replay_data = self.get_replay_data()
            replay_path = self.get_replay_path()
            case_path = replay_path.split('回放数据/')[1]
            arch_path = os.path.join(
                self.replay_arch_path, case_path, str(save_time))
            create_path(arch_path)
            env_info = os.path.join(arch_path, '测试环境信息')
            save_json(env_info, info.base_info())
            dist = os.path.join(arch_path, self.case_num.text()+'.csv')
            shutil.copyfile(replay_data, dist)

    def get_record_tw_soft_name(self):
        root_item = self.record_tw.invisibleRootItem()
        for i in range(root_item.childCount()):
            child_item = root_item.child(i)
            return child_item.text(0)

    def collect_titles(self, parent_item):
        titles = []
        for i in range(parent_item.childCount()):
            item = parent_item.child(i)
            titles.append(item.text(0))
            self.collect_titles(item)
        return titles

    def find_case(self, parent_dir, sub_dir):
        for root, dirs, files in os.walk(parent_dir):
            if sub_dir in dirs:
                return True, os.path.abspath(os.path.join(root, sub_dir))
        return False, None

    def search_case(self, text):
        titles = self.collect_titles(self.record_tw.invisibleRootItem())
        search_case_num = self.search_box.text()
        if search_case_num in titles:
            self.case_num.setText(search_case_num)

        soft_name = self.get_record_tw_soft_name()
        if soft_name != None:
            soft_path = os.path.join(self.record_path, soft_name)
            result = self.find_case(soft_path, search_case_num)
            if result[0]:
                case_path = result[1]
                model_name = case_path.split("/")[6]
                case_path = os.path.join(
                    case_path, case_path.split("/")[-1]+'.csv')
                if os.path.exists(case_path):
                    self.project_name.setText(soft_name)
                    self.case_name.setText(model_name)
                    self.case_num.setText(search_case_num)
                    df = pd.read_csv(case_path, index_col=0)
                    self.case_title.setText(df.index.name)
                    self.show_data(case_path)
        else:
            QMessageBox.critical(self, "错误", "请在测试软件数据存在时搜索用例!")

    def preprocess_home_file(self):
        get_visible_file()
